package com.cmict.data.bpm.framework.flowable.core.listener;

import com.cmict.data.bpm.controller.admin.task.vo.task.BpmTaskRespVO;
import com.cmict.data.bpm.service.message.UserMessageListService;
import com.cmict.data.bpm.service.message.dto.BpmMessageSendWhenTaskCreatedReqDTO;
import com.cmict.data.bpm.service.task.BpmProcessInstanceService;
import com.cmict.data.bpm.service.task.BpmTaskService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.flowable.bpmn.model.Process;
import org.flowable.bpmn.model.*;
import org.flowable.engine.delegate.TaskListener;
import org.flowable.engine.impl.util.ProcessDefinitionUtil;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.service.delegate.DelegateTask;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import static com.cmict.data.bpm.base.constant.FlowableConstant.REJECT_IDENTIFY;

/**
 * @author liutao
 * @date 2022/5/26
 */
@Slf4j
@Component
public class TaskCompleteMessageListener implements TaskListener {

    @Resource
    private BpmProcessInstanceService processInstanceService;
    @Resource
    private BpmTaskService bpmTaskService;
    @Resource
    private UserMessageListService messageListService;
    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public void notify(DelegateTask delegateTask) {
        BpmMessageSendWhenTaskCreatedReqDTO reqDTO = new BpmMessageSendWhenTaskCreatedReqDTO();
        reqDTO.setIsRemind(false);
        /**
         * 超时提醒 开始---------
         */
        Process process = ProcessDefinitionUtil.getProcess(delegateTask.getProcessDefinitionId());
        FlowNode flowNode = (FlowNode) process.getFlowElement(delegateTask.getTaskDefinitionKey());

        Map<String, List<ExtensionElement>> extensionElements = flowNode.getExtensionElements();
        for (String key : extensionElements.keySet()) {
            if(key.equals("remind")){
                List<ExtensionElement> remind = extensionElements.get("remind");
                Map<String, List<ExtensionAttribute>> remindTy = remind.get(0).getChildElements().get("remindTy").get(0).getAttributes();
                String isRemind = remindTy.get("enable").get(0).getValue(); //是否开启
                String time = remindTy.get("time").get(0).getValue();   //  超时时间
                String message = remindTy.get("message").get(0).getValue(); // 消息间隔
                String frequency = remindTy.get("frequency").get(0).getValue(); //推送次数
                // true 开启 超时提醒
                if(StringUtils.isNoneBlank(isRemind) && isRemind.equals("true")){
                    reqDTO.setIsRemind(true);
                    reqDTO.setTime(new BigDecimal(time));
                    reqDTO.setMessage(new BigDecimal(message));
                    reqDTO.setFrequency(Integer.valueOf(frequency));
                    reqDTO.setCompleterFrequency(1); //从1开始计算
//                    String sql = "SELECT id FROM `bpm_task_ext` WHERE task_id = '"+ delegateTask.getId() +"' and process_instance_id = '"+delegateTask.getProcessInstanceId() +"'";
//                    Long bpmTaskExtId =   bpmTaskService.getIdByTaskIdAndProcessinstanceId(sql);
                    reqDTO.setRemindId(delegateTask.getId());
                }
            }
        }

        /**
         *  获取通知方式
         */
//        //获取当前节点输出连线
        List<SequenceFlow> outgoingFlows = flowNode.getOutgoingFlows();
        //遍历输出连线
        List channelList = new ArrayList<>();
        for (SequenceFlow ingoingFlow : outgoingFlows) {
            //获取输出节点元素
            FlowElement sourceFlowElement = ingoingFlow.getSourceFlowElement();
//            //排除非用户任务接点
            if(sourceFlowElement instanceof UserTask){
                List<FlowableListener> taskListeners = ((UserTask) sourceFlowElement).getTaskListeners();
                for (FlowableListener taskListener : taskListeners) {
                    List<FieldExtension> fieldExtensions = taskListener.getFieldExtensions();
                    for (FieldExtension fieldExtension : fieldExtensions) {
                        if(fieldExtension.getFieldName().equals("邮件") || fieldExtension.getFieldName().equals("站内信") ){
//                        if(fieldExtension.getFieldName().equals("邮件") || fieldExtension.getFieldName().equals("站内信") || fieldExtension.getFieldName().equals("短信")){
                            channelList.add(Integer.valueOf(fieldExtension.getStringValue()));
                        }
                    }
                }
            }
        }

        log.info("流程任务匹配完成，执行消息通知------");
        reqDTO.setChannel(channelList);
        BeanUtils.copyProperties(delegateTask, reqDTO);
        ProcessInstance processInstance = processInstanceService.getProcessInstance(reqDTO.getProcessInstanceId());
        String assignee = delegateTask.getAssignee();
        String eventName = delegateTask.getEventName();
        reqDTO.setAssigneeUserId(Long.parseLong(assignee));
        reqDTO.setProcessInstanceName(processInstance.getProcessDefinitionName());
        String startUserId = processInstance.getStartUserId();
        List<BpmTaskRespVO> taskextList = bpmTaskService.getTaskListByProcessInstanceId(processInstance.getId());
        if(taskextList.size() == 0 && reqDTO.getAssigneeUserId() !=null && reqDTO.getAssigneeUserId().toString().equals(startUserId)){
            return;  // 流程图 第一个节点设置 为发起人 不会发消息
        }
        String isReject = stringRedisTemplate.opsForValue().get(reqDTO.getProcessInstanceId());
        if (StringUtils.isNoneBlank(isReject) && isReject.equals(REJECT_IDENTIFY)) {
            messageListService.sendMessageWhenTaskRejected(reqDTO);
        } else {
            messageListService.sendMessageWhenTaskAssigned(reqDTO);
        }
    }
}
